using UnityEngine;

using System.Collections;

public class TreeNode
{



	public int x;

	public int y;

	public int height;

	public int width;

	public TreeNode leftChild;

	public TreeNode rightChild;

	private TreeNode parent;

	public static int ratio;

	private int minSize = 50;

	public int roomX = 0;

	public int roomY = 0;

	public int roomWidth;

	public int roomHeight;

	public bool horizontal;

	public static int counter = 1;

	public static int minRoomSize = 0;

	public static int maxRoomSize = 100;

//public int[] tileMap;






	//The constructor for the treenNode
	
	public TreeNode (int pX, int pY, int pWidth, int pHeight)
	{
		
		this.x = pX;
		
		this.y = pY;
		
		this.height = pHeight;
		
		this.width = pWidth;
		
		leftChild = null;
		
		rightChild = null;
		
		parent = null;
		
	}


	//Splits the dungeon and creates a list for the splits
	
	public bool split ()
	{
		
		
		if (leftChild != null) {
			
			leftChild.split ();
			
			rightChild.split ();
			
			return true;
			
		
		
		} else {
			
			horizontal = TorF ();
			//need to make a random function for this (done)
			minSize = this.width / 3;
			
			int max = (horizontal ? height : width) - minSize;
			
			
			if (max < minSize) {
				
				minSize /= 2;
				
				max += minSize;
				
			}
			
			int split = RndInt (minSize, max);
			//random function here as well(done)
			
			
			TreeNode[] listA;
			
			
			if (horizontal) {
				
				leftChild = new TreeNode (x, y, width, split);
				
				rightChild = new TreeNode (x, y + split, width, height - split);
				
				Buttons.list[counter] = leftChild;
				
				counter++;
				
				Buttons.list[counter] = rightChild;
				
				counter++;
				
				listA = Buttons.list;
				
				Buttons.list = new TreeNode[listA.Length + 2];
				
				
				for (int i = 0; i < listA.Length; i++) {
					
					Buttons.list[i] = listA[i];
					
				}
				
			
			
			} else {
				
				leftChild = new TreeNode (x, y, split, height);
				
				rightChild = new TreeNode (x + split, y, width - split, height);
				
				Buttons.list[counter] = leftChild;
				
				counter++;
				
				Buttons.list[counter] = rightChild;
				
				counter++;
				
				listA = Buttons.list;
				
				Buttons.list = new TreeNode[listA.Length + 2];
				
				
				for (int i = 0; i < listA.Length; i++) {
					
					Buttons.list[i] = listA[i];
					
				}
				
			}
			
			
			
			rightChild.parent = this;
			
			leftChild.parent = this;
			
			
			
			return true;
			
		}
		
	}


	//creates the rooms in the splits
	//need to finish(done)
	public void generateRooms ()
	{
		
		
		if (leftChild != null) {
			
			leftChild.generateRooms ();
			
			rightChild.generateRooms ();
			
		
		
		} else {
			
			
			if (parent != null) {
				
				//will ensure an overlap between sister node rooms
				if (parent.horizontal) {
					
					int min = this.width / 2 + 1;
					
					
					if (min < Buttons.minRoomSize) {
						
						min = Buttons.minRoomSize;
						
					}
					
					roomX = Random.Range (this.x + 1, this.x + this.width - 1 - min);
					
					roomY = RndInt (this.y + 1, this.y + this.height - (Buttons.minRoomSize + 1));
					
					roomWidth = Random.Range (min, (int)(((this.x + this.width) * (Buttons.maxRoomSize / 100.0)) - 1) - this.roomX);
					
					roomHeight = Random.Range (Buttons.minRoomSize, (int)((this.height - (roomY - y)) * (Buttons.maxRoomSize / 100.0)) - 1);
					
				
				
				} else {
					
					int min = this.height / 2 + 1;
					
					
					if (min < Buttons.minRoomSize) {
						
						min = Buttons.minRoomSize;
						
					}
					
					roomX = Random.Range (this.x + 1, this.x + this.width - (Buttons.minRoomSize + 1));
					
					roomY = Random.Range (this.y + 1, this.y + this.height - 1 - min);
					
					roomWidth = Random.Range (Buttons.minRoomSize, (int)((this.width - (roomX - x)) * (Buttons.maxRoomSize / 100.0)) - 1);
					
					roomHeight = Random.Range (min, (int)(((this.y + this.height) * (Buttons.maxRoomSize / 100.0)) - 1) - this.roomY);
					
				}
				
			
			
			} else {
				
				int min = this.width / 2 + 1;
				
				roomX = Random.Range (x + 1, width - 1 - min);
				
				roomY = Random.Range (y + 1, height - 1 - min);
				
				roomWidth = Random.Range (min, (x + width - 1) - roomX);
				
				roomHeight = Random.Range (min, (y + height - 1) - roomY);
				
			}
			
		}
		
	}


	//generates the cooridors to each of the rooms
	
	public void generateCorridors (int index)
	{
		
		if (index == counter)
			index = index / 2 - 1;
		
		
		
		
		if (index >= 0) {
			
			
			if (Buttons.list[index] != null) {
				
				int leftMin, rightMin, leftMax, rightMax;
				
				int minBound, maxBound;
				
				
				
				
				if (Buttons.list[index].horizontal) {
					
					
					if (Buttons.list[index].rightChild.rightChild == null) {
						
						leftMin = Buttons.list[index].leftChild.roomX;
						
						rightMin = Buttons.list[index].rightChild.roomX;
						
						leftMax = (Buttons.list[index].leftChild.roomX + Buttons.list[index].leftChild.roomWidth);
						
						rightMax = (Buttons.list[index].rightChild.roomX + Buttons.list[index].rightChild.roomWidth);
						
						
						
						minBound = (leftMin < rightMin ? rightMin : leftMin);
						
						maxBound = (leftMax > rightMax ? rightMax - 2 : leftMax - 2);
						
						
						
						Buttons.list[index].roomX = RndInt (minBound, maxBound);
						
						Buttons.list[index].roomY = Buttons.list[index].leftChild.roomY + Buttons.list[index].leftChild.roomHeight;
						
						Buttons.list[index].roomWidth = 1;
						
						Buttons.list[index].roomHeight = Buttons.list[index].rightChild.roomY - Buttons.list[index].roomY;
						
					
					
					} else {
						
						leftMin = Buttons.list[index].leftChild.GetMinHor ();
						
						rightMin = Buttons.list[index].rightChild.GetMinHor ();
						
						leftMax = Buttons.list[index].leftChild.GetMaxHor ();
						
						rightMax = Buttons.list[index].rightChild.GetMaxHor ();
						
						
						
						minBound = (leftMin < rightMin ? rightMin : leftMin);
						
						maxBound = (leftMax > rightMax ? rightMax - 2 : leftMax - 2);
						
						
						
						Buttons.list[index].roomX = RndInt (minBound, maxBound);
						
						Buttons.list[index].roomY = Buttons.list[index].SearchLeftHor (Buttons.list[index].roomX, index);
						
						Buttons.list[index].roomWidth = 1;
						
//Buttons.list[index].roomHeight = 20;
						
						Buttons.list[index].roomHeight = Buttons.list[index].SearchRightHor (Buttons.list[index].roomX, index) - Buttons.list[index].roomY;
						
					}
					
				
				
				} else {
					
					
					if (Buttons.list[index].rightChild.rightChild == null) {
						
						leftMin = Buttons.list[index].leftChild.roomY;
						
						rightMin = Buttons.list[index].rightChild.roomY;
						
						leftMax = (Buttons.list[index].leftChild.roomY + Buttons.list[index].leftChild.roomHeight);
						
						rightMax = (Buttons.list[index].rightChild.roomY + Buttons.list[index].rightChild.roomHeight);
						
						
						
						minBound = (leftMin < rightMin ? rightMin : leftMin);
						
						maxBound = (leftMax > rightMax ? rightMax - 2 : leftMax - 2);
						
						
						
						Buttons.list[index].roomY = RndInt (minBound, maxBound);
						
						Buttons.list[index].roomX = Buttons.list[index].leftChild.roomX + Buttons.list[index].leftChild.roomWidth;
						
						Buttons.list[index].roomHeight = 1;
						
						Buttons.list[index].roomWidth = Buttons.list[index].rightChild.roomX - Buttons.list[index].roomX;
						
					
					
					} else {
						
						leftMin = Buttons.list[index].leftChild.GetMinVert ();
						
						rightMin = Buttons.list[index].rightChild.GetMinVert ();
						
						leftMax = Buttons.list[index].leftChild.GetMaxVert ();
						
						rightMax = Buttons.list[index].rightChild.GetMaxVert ();
						
						
						
						minBound = (leftMin < rightMin ? rightMin : leftMin);
						
						maxBound = (leftMax > rightMax ? rightMax - 2 : leftMax - 2);
						
						
						
						Buttons.list[index].roomY = RndInt (minBound, maxBound);
						
						Buttons.list[index].roomX = Buttons.list[index].SearchLeftVert (Buttons.list[index].roomY, index);
						
						Buttons.list[index].roomHeight = 1;
						
						Buttons.list[index].roomWidth = Buttons.list[index].SearchRightVert (Buttons.list[index].roomY, index) - Buttons.list[index].roomX;
						
					}
					
				}
				
				
				
				generateCorridors (index - 1);
				
			}
			
		}
		
		
		
	}



	
	private bool TorF ()
	{
		
		int rnd = Random.Range (0, 1000);
		
		
		if (rnd > 500 && (float)height / (float)width > 1.0 / (float)ratio) {
			
			return true;
			
		
		
		} else if ((float)width / (float)height > 1.0 / (float)ratio) {
			
			return false;
			
		
		
		} else {
			
			return true;
			
		}
		
	}



	
	private int RndInt (int min, int max)
	{
		
		return Random.Range (min, max);
		
	}



	
	private int GetMinHor ()
	{
		
		TreeNode cur = this;
		
		int min = Buttons.list[0].x + Buttons.list[0].width;
		
		
		while (cur != null) {
			
			
			
			
			if (min > cur.roomX) {
				
				min = cur.roomX;
				
			}
			
			cur = cur.leftChild;
			
		}
		
		return min;
		
	}



	
	private int GetMaxHor ()
	{
		
		TreeNode cur = this;
		
		int max = Buttons.list[0].x;
		
		
		while (cur != null) {
			
			
			
			
			if (max < cur.roomX + cur.roomWidth) {
				
				max = cur.roomX + cur.roomWidth;
				
			}
			
			cur = cur.rightChild;
			
		}
		
		return max;
		
	}



	
	private int GetMinVert ()
	{
		
		TreeNode cur = this;
		
		int min = Buttons.list[0].y + Buttons.list[0].height;
		
		
		while (cur != null) {
			
			
			
			
			if (min > cur.roomY) {
				
				min = cur.roomY;
				
			}
			
			cur = cur.leftChild;
			
		}
		
		return min;
		
	}



	
	private int GetMaxVert ()
	{
		
		TreeNode cur = this;
		
		int max = Buttons.list[0].y;
		
		
		while (cur != null) {
			
			
			
			
			if (max < cur.roomY + cur.roomHeight) {
				
				max = cur.roomY + cur.roomHeight;
				
			}
			
			cur = cur.rightChild;
			
		}
		
		return max;
		
	}



	
	private int SearchLeftHor (int corX, int pIndex)
	{
		
		int yNeed = Buttons.list[0].y;
		
		int repeat = 1;
		
		
		if (this.leftChild.roomX <= corX && corX < this.leftChild.roomX + this.leftChild.roomWidth) {
			
			
			if (yNeed <= this.leftChild.roomY + this.leftChild.roomHeight) {
				
				yNeed = this.leftChild.roomY + this.leftChild.roomHeight;
				
			}
			
		}
		
		
		for (int i = (pIndex * 2 + 1) * 2 + 1; i < counter; i = i * 2 + 1) {
			
			repeat *= 2;
			
			
			for (int j = 0; j < repeat; j++) {
				
				
				if (Buttons.list[i + j].roomX <= corX && corX < Buttons.list[i + j].roomX + Buttons.list[i + j].roomWidth) {
					
					
					if (yNeed <= Buttons.list[i + j].roomY + Buttons.list[i + j].roomHeight) {
						
						yNeed = Buttons.list[i + j].roomY + Buttons.list[i + j].roomHeight;
						
					}
					
				}
				
			}
			
		}
		
		
		
		return yNeed;
		
	}



	
	private int SearchRightHor (int corX, int pIndex)
	{
		
		int yNeed = Buttons.list[0].y + Buttons.list[0].height;
		
		int repeat = 1;
		
		
		if (this.rightChild.roomX <= corX && corX < this.rightChild.roomX + this.rightChild.roomWidth) {
			
			
			if (yNeed >= this.rightChild.roomY + this.rightChild.roomHeight) {
				
				yNeed = this.rightChild.roomY + this.rightChild.roomHeight;
				
			}
			
		}
		
		
		for (int i = (pIndex * 2 + 2) * 2 + 1; i < counter; i = i * 2 + 1) {
			
			repeat *= 2;
			
			
			for (int j = 0; j < repeat; j++) {
				
				
				if (Buttons.list[i + j].roomX <= corX && corX < Buttons.list[i + j].roomX + Buttons.list[i + j].roomWidth) {
					
					
					if (yNeed >= Buttons.list[i + j].roomY) {
						
						yNeed = Buttons.list[i + j].roomY;
						
					}
					
				}
				
			}
			
		}
		
		
		
		return yNeed;
		
	}



	
	private int SearchLeftVert (int corY, int pIndex)
	{
		
		int xNeed = Buttons.list[0].x;
		
		int repeat = 1;
		
		
		if (this.leftChild.roomY <= corY && corY < this.leftChild.roomY + this.leftChild.roomHeight) {
			
			
			if (xNeed <= this.leftChild.roomX + this.leftChild.roomWidth) {
				
				xNeed = this.leftChild.roomX + this.leftChild.roomWidth;
				
			}
			
		}
		
		
		for (int i = (pIndex * 2 + 1) * 2 + 1; i < counter; i = i * 2 + 1) {
			
			repeat *= 2;
			
			
			for (int j = 0; j < repeat; j++) {
				
				
				if (Buttons.list[i + j].roomY <= corY && corY < Buttons.list[i + j].roomY + Buttons.list[i + j].roomHeight) {
					
					
					if (xNeed <= Buttons.list[i + j].roomX + Buttons.list[i + j].roomWidth) {
						
						xNeed = Buttons.list[i + j].roomX + Buttons.list[i + j].roomWidth;
						
					}
					
				}
				
			}
			
		}
		
		
		
		return xNeed;
		
	}



	
	private int SearchRightVert (int corY, int pIndex)
	{
		
		int xNeed = Buttons.list[0].x + Buttons.list[0].width;
		
		int repeat = 1;
		
		
		if (this.rightChild.roomY <= corY && corY < this.rightChild.roomY + this.rightChild.roomHeight) {
			
			
			if (xNeed >= this.rightChild.roomX + this.rightChild.roomWidth) {
				
				xNeed = this.rightChild.roomX + this.rightChild.roomWidth;
				
			}
			
		}
		
		
		for (int i = (pIndex * 2 + 2) * 2 + 1; i < counter; i = i * 2 + 1) {
			
			repeat *= 2;
			
			
			for (int j = 0; j < repeat; j++) {
				
				
				if (Buttons.list[i + j].roomY <= corY && corY < Buttons.list[i + j].roomY + Buttons.list[i + j].roomHeight) {
					
					
					if (xNeed >= Buttons.list[i + j].roomX) {
						
						xNeed = Buttons.list[i + j].roomX;
						
					}
					
				}
				
			}
			
		}
		
		
		
		return xNeed;
		
	}
	
}
